package pong;

import java.io.DataInputStream;
import java.io.DataOutputStream;

import javax.bluetooth.DataElement;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.ServiceRecord;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.io.StreamConnectionNotifier;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;


public class PongMidlet extends MIDlet
{
	private Display mDisplay; 
	private Command exitCmd;			
	private List mainMenu;
	private PongCanvas gameScreen;
	private boolean endNow;
	
	protected boolean waitingConnection;

	private StreamConnection conn;
	private DataOutputStream out;
	private DataInputStream in;
	
	public int game_type;


	public PongMidlet() 
	{
		init();
	}

	public void sendBall(Ball ball)
	{
		PongMessages.sendBall(out, ball);
	}
	
	private void init() {
		exitCmd = new Command( "Exit", Command.EXIT, 2);
		
		endNow = false;
		waitingConnection = true;

		mainMenu = new List( "Main Menu",  List.IMPLICIT);
		mainMenu.append( "Start", null);
		mainMenu.append( "Setup", null);
		mainMenu.append( "Hall of fame", null);
		mainMenu.append( "Server Mode", null);
		mainMenu.append( "Client Mode", null);
		mainMenu.addCommand( exitCmd);
		mainMenu.setCommandListener( new CommandListener() {
			public void commandAction( Command cmd, Displayable arg1) {
				if( cmd == List.SELECT_COMMAND) {
					int pos = mainMenu.getSelectedIndex();
					switch( pos) {
					case 0: 
						startGame();
						break;
					case 1: 
						setupGame();
						break;
					case 2: 
						hallOfFame();
						break;
					case 3: 
						startServer();
						break;
					case 4: 
						startClient();
						break;
					}
				} else if( cmd == exitCmd) {
					try {
						destroyApp( false);
					} catch( MIDletStateChangeException e) {
						// no error expected
					}
				}
			}
		});
		
		gameScreen = new PongCanvas( this);
	}

	public void destroyApp( boolean arg0) throws MIDletStateChangeException {
		notifyDestroyed();
	}

	protected void pauseApp() {
		// do nothing
	}

	protected void startApp() throws MIDletStateChangeException 
	{
		mDisplay = Display.getDisplay( this);
		showMainMenu();

	}

	private void startServer()
	{
		game_type = PongConstants.GAME_TYPE_MULTI_SERVER;

		
		PongServer pServer = new PongServer();
		pServer.start();	
		
		mDisplay.setCurrent( gameScreen);
		gameScreen.startGame();

	}
	
	protected void startClient() 
	{
		game_type = PongConstants.GAME_TYPE_MULTI_CLIENT;

		new Thread( new Runnable() 
		{
			public void run() 
			{
				try 
				{
					String srv = ServiceDiscoveryUtils.getInstance().getServiceUrl( PongConstants.PongUUID);

					conn = (StreamConnection) Connector.open( srv);
					out = conn.openDataOutputStream();
					in = conn.openDataInputStream();
					
					waitingConnection = false;

					while( ! endNow) 
					{
						Ball new_ball = PongMessages.getBall(in);
						gameScreen.addBall(new_ball);					
					}

					
				} catch( Exception e) {
					Alert a = new Alert( "Error", "Error connecting to the server : " + e.getMessage(), null, null);
					a.setTimeout( 2000);
//					mDisplay.setCurrent( a, mDisplay);
					//e.printStackTrace();
				}
			}
		}).start();
		
		mDisplay.setCurrent( gameScreen);
		gameScreen.startGame();

	}
	
	class PongServer extends Thread 
	{
		public void run() 
		{
			try {
				LocalDevice device = LocalDevice.getLocalDevice();
				device.setDiscoverable( DiscoveryAgent.GIAC);
				
				String url = "btspp://localhost:" + PongConstants.PongUUID + ";name=Pong Server";
				
				StreamConnectionNotifier notifier = (StreamConnectionNotifier)Connector.open( url);
				ServiceRecord record = device.getRecord( notifier);
				record.setAttributeValue( 0x0003,new DataElement( DataElement.UUID, PongConstants.PongUUID));
				device.updateRecord( record);
				
				while(!endNow) 
				{
					PongThread th = new PongThread( notifier.acceptAndOpen());
					th.start();
				}
			} catch( Exception e) {
				Alert a = new Alert( "Alert", "Error on main server : " + e, null, null);
				a.setTimeout( 2000);
//				mDisplay.setCurrent( a, mainWnd);
			}
		}
	}

	class PongThread extends Thread 
	{
		StreamConnection conn;
		PongThread( StreamConnection conn) 
		{
			this.conn = conn;
		}
		public void run() {
			try {
				out = conn.openDataOutputStream();
				in = conn.openDataInputStream();

				waitingConnection = false;

				while( ! endNow) 
				{
					Ball new_ball = PongMessages.getBall(in);
					gameScreen.addBall(new_ball);					
				}
				
				conn.close();
				
			} catch( Exception e) {
				// do nothing
			} finally {
//				remConnection();
			}
		}
	}
	
	void showMainMenu() {
		mDisplay.setCurrent( mainMenu);
	}

	protected void startGame() 
	{
		mDisplay.setCurrent( gameScreen);
		game_type = PongConstants.GAME_TYPE_SINGLE;
		gameScreen.startGame();
	}
	protected void setupGame() {
		// TODO: to complete
		Alert alert = new Alert( "Setup", "Setup selected", null, null);
		alert.setTimeout(5000);
		mDisplay.setCurrent( alert, mainMenu);
	}
	protected void hallOfFame() {
		// TODO: to complete
		Alert alert = new Alert( "Setup", "Setup selected", null, null);
		alert.setTimeout(5000);
		mDisplay.setCurrent( alert, mainMenu);
	}
	protected void instructions() {
		// TODO: to complete
		Alert alert = new Alert( "Instructions", "Instructions selected", null, null);
		alert.setTimeout(5000);
		mDisplay.setCurrent( alert, mainMenu);
	}
	
	
}

